package com.xy.biz.xd.controller;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.req.ListDictItemRequest;
import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.xd.domain.converter.DocumentFlowNewAndModifyConverter;
import com.xy.biz.xd.domain.query.DocumentFlowNewAndModifyQuery;
import com.xy.biz.xd.domain.req.*;
import com.xy.biz.xd.domain.resp.GetDocumentFlowNewAndModifyResponse;
import com.xy.biz.xd.domain.resp.GetDocumentFlowResponse;
import com.xy.biz.xd.domain.resp.GetDocumentReleaseResponse;
import com.xy.biz.xd.service.DocumentFlowNewAndModifyService;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;
import com.xy.lang.util.ResultUtils;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.*;

import static com.xy.biz.xd.domain.bo.DocumentFlowConstants.*;

@Slf4j
public abstract class AbstractDocumentFlowNewAndModifyController {

    protected DocumentFlowNewAndModifyService documentFlowNewAndModifyService;

    protected abstract void setDocumentFlowNewAndModifyService(DocumentFlowNewAndModifyService documentFlowNewAndModifyService);

    @Autowired
    private DictClient dictClient;

    @ApiOperation("申请审批")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/apply_approval")
    public Result<?> applyApprovalDocumentFlow(@RequestBody HandleDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.applyApprovalDocumentFlow(request);
    }

    @ApiOperation("编辑")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/edit")
    public Result<?> editDocumentFlow(@RequestBody EditDocumentFlowRequest request) {
        if (CollectionUtils.isEmpty(request.getReviewUserIdList())) {
            return Result.ofBadRequest("必须指定至少一个处理人！");
        }
        Set<Long> idSet = new HashSet<>(request.getReviewUserIdList());
        if (!Objects.equals(idSet.size(), request.getReviewUserIdList().size())) {
            return Result.ofBadRequest("不能指定重复的处理人！");
        }
        return documentFlowNewAndModifyService.editDocumentFlow(request);
    }

    @ApiOperation("评审")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/review")
    public Result<?> reviewDocumentFlow(@RequestBody ReviewDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.reviewDocumentFlow(request);
    }

    @ApiOperation("再次编辑")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/edit_again")
    public Result<?> editAgainDocumentFlow(@RequestBody EditAgainDocumentFlowRequest request) {
        if (Objects.equals(request.getResult(), HANDLE_RESULT_REJECT)
                && CollectionUtils.isEmpty(request.getReviewUserIdList())) {
            return Result.ofBadRequest("必须指定至少一个处理人！");
        }
        if (!CollectionUtils.isEmpty(request.getReviewUserIdList())) {
            Set<Long> idSet = new HashSet<>(request.getReviewUserIdList());
            if (Objects.equals(request.getResult(), HANDLE_RESULT_REJECT)
                    && !Objects.equals(idSet.size(), request.getReviewUserIdList().size())) {
                return Result.ofBadRequest("不能指定重复的处理人！");
            }
        }
        return documentFlowNewAndModifyService.editAgainDocumentFlow(request);
    }

    @ApiOperation("格式审核")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/format_audit")
    public Result<?> formatAuditDocumentFlow(@RequestBody HandleDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.formatAuditDocumentFlow(request);
    }

    @ApiOperation("文件审核")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/content_audit")
    public Result<?> contentAuditDocumentFlow(@RequestBody HandleDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.contentAuditDocumentFlow(request);
    }

    @ApiOperation("审批")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/approval")
    public Result<?> approvalDocumentFlow(@RequestBody HandleDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.approvalDocumentFlow(request);
    }

//    @ApiOperation("放行")
//    @Validatable(groups = {UpdateChecks.class})
//    @PostMapping(value = "/release")
//    public Result<?> releaseDocumentFlow(@RequestBody ReleaseDocumentFlowRequest request) {
//        return documentFlowNewAndModifyService.releaseDocumentFlow(request);
//    }


    @ApiOperation("获取当前新增流程信息")
    @PostMapping(value = "/getDocumentFlowNewAndModify")
    public Result<?> getDocumentFlowNew(@RequestBody GetDocumentFlowNewAndModifyRequest request) {
        return documentFlowNewAndModifyService.getDocumentFlowNewAndModify(request.getDocumentFlowId());
    }

    @ApiOperation("体系培训")
    @PostMapping(value = "/list_train_by_document_flow")
    public Result<List<GetDocumentFlowNewAndModifyResponse>> listTrainByDocumentFlow(@RequestBody ListDocumentFlowNewAndModifyRequest request) {
        DocumentFlowNewAndModifyQuery query = DocumentFlowNewAndModifyConverter.toQuery(request);
        List<GetDocumentFlowNewAndModifyResponse> list = DocumentFlowNewAndModifyConverter.toResponse2(documentFlowNewAndModifyService.listDocumentFlowNewAndModify(query));
        buildGetDocumentFlowResponse(list);
        return Result.success(list);
    }

    private Map<Integer, String> getFlowTypeMap() {
        List<ListDictItemResponse> listDictItemResponseList
                = ResultUtils.get(dictClient.listDictItem(ListDictItemRequest.builder().dictGroupCode("flow_type").build()));
        Map<Integer, String> flowTypeMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(listDictItemResponseList)) {
            try {
                listDictItemResponseList.forEach(e -> flowTypeMap.put(Integer.parseInt(e.getDictCode()), e.getDictValue()));
            } catch (Exception e) {
                log.error("流程类型编码转换错误", e);
            }
        }
        return flowTypeMap;
    }

    /*@ApiOperation("取消流程（撤回后重新处理本节点）")
    @Validatable
    @PostMapping(value = "/withdraw")
    public Result<?> withdraw(@RequestBody HandleDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.withdraw(request);
    }*/

    @ApiOperation("终止流程")
    @Validatable(groups = {UpdateChecks.class})
    @PostMapping(value = "/termination")
    public Result<?> termination(@RequestBody HandleDocumentFlowRequest request) {
        return documentFlowNewAndModifyService.termination(request);
    }

    private void buildGetDocumentFlowResponse(List<GetDocumentFlowNewAndModifyResponse> list) {
        if (!CollectionUtils.isEmpty(list)) {
            Map<Integer, String> flowTypeMap = getFlowTypeMap();
            for (GetDocumentFlowNewAndModifyResponse getDocumentFlowResponse : list) {
                getDocumentFlowResponse.setFlowTypeName(flowTypeMap.get(getDocumentFlowResponse.getFlowType()));
                getDocumentFlowResponse.setPhaseName(getPhaseName(getDocumentFlowResponse.getFlowType(), getDocumentFlowResponse.getPhase()));
                if (Objects.equals(URGENT_NORMAL, getDocumentFlowResponse.getUrgent())) {
                    getDocumentFlowResponse.setUrgentName("正常");
                } else if (Objects.equals(URGENT_URGENT, getDocumentFlowResponse.getUrgent())) {
                    getDocumentFlowResponse.setUrgentName("紧急");
                } else {
                    getDocumentFlowResponse.setUrgentName(getDocumentFlowResponse.getUrgent());
                }
            }
        }
    }

    private void buildGetDocumentReleaseResponse(List<GetDocumentReleaseResponse> list) {
        if (!CollectionUtils.isEmpty(list)) {
            Map<Integer, String> flowTypeMap = getFlowTypeMap();
            for (GetDocumentReleaseResponse getDocumentReleaseResponse : list) {
                getDocumentReleaseResponse.setFlowTypeName(flowTypeMap.get(getDocumentReleaseResponse.getFlowType()));
            }
        }
    }

}
